/******************************************************************************
 * Student Name: Ofri Keidar
 * Exercise Name: Ex2
 * File Description: Class StudentLinkedList's interface
 ******************************************************************************/

#ifndef STUDENTLINKEDLIST_H
#define STUDENTLINKEDLIST_H

#include "Student.h"
#define ID_ERROR_VAL -1 // value to indicate error in id attribute
#define NAME_ERROR_VAL "ERROR" // value to indicate error in name attribute

class StudentLinkedList {

private:
	class Node {

		private:
			/***************************************************************************************
			 * function name: Node(const Node& node)
			 * The Input: Node to be copied
			 * The output: None
			 * The Function operation: The copy constructor is an empty-implementation
			 * 						   because node objects should not be sent to functions
			 * 						   by value
			 ***************************************************************************************/
			Node(const Node& node) {}

		public:
			Student* m_studentData; // pointer to student data
			Node* m_prevNode; // pointer to previous node on list
			Node* m_nextNode; // pointer to next node on list
			int m_index; // node's index in list

			/***************************************************************************************
			 * function name: Node (Student* studentToPoint)
			 * The Input: Student data to point at
			 * The output: None
			 * The Function operation: Creates a new node pointing to given student
			 ***************************************************************************************/
			Node (Student* studentToPoint);

			/****************************************************************************************
			 * function name: ~Node()
			 * The Input: None
			 * The output: None
			 * The Function operation: Destructs node object
			 ***************************************************************************************/
			~Node();

			/****************************************************************************************
			 * function name: setIndex(const int newIndex)
			 * The Input: New index for node
			 * The output: None
			 * The Function operation: Sets index attribute as given value
			 ***************************************************************************************/
			void setIndex(const int newIndex) {m_index = newIndex;}
	};


	Node* m_headDummy; // pointer to first node on list
	Node* m_tailDummy; // pointer to last node on list
	Node* m_currentNode; // node pointer that the user can change the node that it points at at get it's data


	/***************************************************************************************
	 * function name: StudentLinkedList(const StudentLinkedList& list)
	 * The Input: List to be copied
	 * The output: None
	 * The Function operation: The copy constructor is private and an empty-implementation
	 * 						   because student linked list objects should not be sent to
	 * 						   functions by value
	 ***************************************************************************************/
	StudentLinkedList(const StudentLinkedList& list) {}

	/***************************************************************************************
	 * function name: findPlace(Student* newStudent)
	 * The Input: Pointer to student to add
	 * The output: Node pointer to which the new student should be linked.
	 * 			   If a student with new student's id alreafy exists, NULL is returned
	 * The Function operation: The method checks if a student with the new studet's id already
	 * 						   exists. If no such student was found, the method returns a
	 * 						   node pointer which before it new student will be linked
	 ***************************************************************************************/
	Node* findPlace(const Student& newStudent) const;

	/***************************************************************************************
	 * function name: internalAdd(Student& newStudent, Node* before)
	 * The Input: Pointer to student to be added and a pointer to the node where the new
	 * 			  student will be linked
	 * The output: None
	 * The Function operation: The method creates a new node pointing to the new student
	 * 						   and links the new node in the given location to the list
	 ***************************************************************************************/
	void internalAdd(Student& newStudent, Node* before);

	/****************************************************************************************
	 * function name: setNodeIndex(Node* const nodeToUpdt, const int newIndex)
	 * The Input: Pointer to the node whose index needed to be change and new index for node
	 * The output: None
	 * The Function operation: Sets given node's index according to given value
	 ***************************************************************************************/

public:
	/***************************************************************************************
	 * function name: StudentLinkedList()
	 * The Input: None
	 * The output: None
	 * The Function operation: Creates a new student linked list
	 ***************************************************************************************/
	StudentLinkedList();

	/***************************************************************************************
	 * function name: ~StudentLinkedList()
	 * The Input: None
	 * The output: None
	 * The Function operation: Deletes the student linked list and the pointed data
	 ***************************************************************************************/
	~StudentLinkedList();

	/***************************************************************************************
	 * function name: addNode(Student* newStudent)
	 * The Input: Pointer to student to be added
	 * The output: True if student was added, False is not
	 * The Function operation: If there is already a student with the new student's id,
	 * 						   student is not added.
	 * 						   Otherwise, it adds the student and keeps the list sorted
	 * 						   from lowest id value to highest
	 ***************************************************************************************/
	bool addNode(Student* newStudent);

	/***************************************************************************************
	 * function name: initCurrent()
	 * The Input: None
	 * The output: None
	 * The Function operation: Sets current node pointer to list's head
	 ***************************************************************************************/
	void initCurrent() {m_currentNode = m_headDummy;}

	/***************************************************************************************
	 * function name: incrmntCurrent()
	 * The Input: None
	 * The output: False if end is reached, True if not
	 * The Function operation: Increments current node pointer. If points at lists end
	 * 						   returned value is False, otherwise True
	 ***************************************************************************************/
	bool incrmntCurrent();

	/***************************************************************************************
	 * function name: getCurrentID()
	 * The Input: None
	 * The output: Id of student which current node pointer points at.
	 * 			   If current node points at no student, ID_ERROR_VAL is returned
	 * The Function operation: Checks if student pointer is NULL. If so, returns ID_VAL_ERROR.
	 * 					       Otherwise returns student's id. Method does not change
	 * 					       the object
	 ***************************************************************************************/
	int getCurrentID() const;

	/***************************************************************************************
	 * function name: getCurrentName()
	 * The Input: None
	 * The output: Name of student which current node pointer points at.
	 * 			   If current node points at no student, NAME_ERROR_VAL is returned
	 * The Function operation: Checks if student pointer is NULL. If so, returns NAME_VAL_ERROR.
	 * 					       Otherwise returns student's name. Method does not change
	 * 					       the object
	 ***************************************************************************************/
	string getCurrentName() const;

	/***************************************************************************************
	 * function name: searchByKey(const int key)
	 * The Input: Id to look for
	 * The output: Pointer to student whose id matches given value. If no such student
	 * 			   exists, NULL is returned.
	 * The Function operation: Scans list- if a match is found, a pointer to this student
	 * 						   is returned. If not, NULL is returned.
	 * 						   Method does not change list object
	 ***************************************************************************************/
	Student* searchByKey(const int key) const;

	/***************************************************************************************
	 * function name: searchByIndex(const int index)
	 * The Input: Index to look for
	 * The output: Pointer to student whose index in list matches given value. If no such
	 * 			   student exists, NULL is returned.
	 * The Function operation: Scans list- if a match is found, a pointer to this student
	 * 						   is returned. If not, NULL is returned
	 * 						   Method does not change list object
	 ***************************************************************************************/
	Student* searchByIndex(const int index) const ;

	/***************************************************************************************
	 * function name: getCurrentStudent()
	 * The Input: None
	 * The output: Pointer to student that current node points at
	 * The Function operation: Returns pointer to student data attribute of the node which
	 * 					       is pointed by current node pointer
	 ***************************************************************************************/
	Student* getCurrentStudent() const {return m_currentNode->m_studentData;}

	/***************************************************************************************
	 * function name: setCurrentStudentPointer(Student* newStudent)
	 * The Input: New student for current node to point at
	 * The output: None
	 * The Function operation: Sets current node's index to given value
	 ***************************************************************************************/
	void setCurrentStudentPointer(Student* newStudent);
};

#endif
